package com.unswift.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

import javax.imageio.ImageIO;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;

@Api(value="图片公共操作类", author="unswift", date="2023-05-26", version="1.0.0")
public final class ImageUtils {

	@ApiField("验证码随机组合字符")
	public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
	@ApiField("java机器人对象")
	public static Robot robot=createRobot();
	
	@ApiMethod(value="生成图形验证码", params={@ApiField("输出流"), @ApiField("验证码字符数量"), @ApiField("图片宽度"), @ApiField("图片高度")})
	public static String generateCaptcha(OutputStream output, int verifySize, int width, int height) {
		return generateCaptcha(output, verifySize, VERIFY_CODES, width, height);
	}
	
	@ApiMethod(value="生成图形验证码-逻辑实现", params={@ApiField("输出流"), @ApiField("验证码字符数量"), @ApiField("图形验证码字符集合"), @ApiField("图片宽度"), @ApiField("图片高度")})
	private static String generateCaptcha(OutputStream output, int verifySize, String sources, int width, int height) {
		if (sources == null || sources.length() == 0) {
			sources = VERIFY_CODES;
		}
		int codesLen = sources.length();
		Random rand = new Random(System.currentTimeMillis());
		StringBuilder verifyCode = new StringBuilder(verifySize);
		for (int i = 0; i < verifySize; i++) {
			verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
		}
		String code=verifyCode.toString();
		numberToOutputImage(width, height, output, code);
		return code;
	}
	
	@ApiMethod(value="将字符串转换为图片并写入输出流中", params={@ApiField("图形宽度"), @ApiField("图形高度"), @ApiField("输出流"), @ApiField("字符串")})
	private static void numberToOutputImage(int w, int h, OutputStream os, String code) {
		try {
			int verifySize = code.length();
			BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			Random rand = new Random();
			Graphics2D g2 = image.createGraphics();
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			Color[] colors = new Color[5];
			Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA,
					Color.ORANGE, Color.PINK, Color.YELLOW };
			float[] fractions = new float[colors.length];
			for (int i = 0; i < colors.length; i++) {
				colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
				fractions[i] = rand.nextFloat();
			}
			Arrays.sort(fractions);
			
			g2.setColor(Color.GRAY);// 设置边框色
			g2.fillRect(0, 0, w, h);
			Random random = new Random();
			Color c = getRandColor(200, 250, random);
			g2.setColor(c);// 设置背景色
			g2.fillRect(0, 2, w, h - 4);
			
			// 绘制干扰线
			g2.setColor(getRandColor(160, 200, random));// 设置线条的颜色
			for (int i = 0; i < 20; i++) {
				int x = random.nextInt(w - 1);
				int y = random.nextInt(h - 1);
				int xl = random.nextInt(6) + 1;
				int yl = random.nextInt(12) + 1;
				g2.drawLine(x, y, x + xl + 40, y + yl + 20);
			}
			
			// 添加噪点
			float yawpRate = 0.05f;// 噪声率
			int area = (int) (yawpRate * w * h);
			for (int i = 0; i < area; i++) {
				int x = random.nextInt(w);
				int y = random.nextInt(h);
				int rgb = getRandomIntColor(random);
				image.setRGB(x, y, rgb);
			}
			
			shear(g2, w, h, c, random);// 使图片扭曲
			
			g2.setColor(getRandColor(100, 160, random));
			int fontSize = h - 4;
			Font font = new Font("Algerian", Font.ITALIC, fontSize);
			g2.setFont(font);
			char[] chars = code.toCharArray();
			for (int i = 0; i < verifySize; i++) {
				AffineTransform affine = new AffineTransform();
				affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1),
						(w / verifySize) * i + fontSize / 2, h / 2);
				g2.setTransform(affine);
				g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 5);
			}
			
			g2.dispose();
			ImageIO.write(image, "jpg", os);
		} catch (Exception e) {
			e.printStackTrace();
			throw ExceptionUtils.exception("generate.verify.code.exception", e, e.getMessage());
		}
	}
	
	@ApiMethod(value="获取随机颜色值", params={@ApiField("颜色基础值"), @ApiField("增量最大值"), @ApiField("随机对象")}, returns=@ApiField("颜色值"))
	private static Color getRandColor(int fc, int bc, Random random) {
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}
	
	@ApiMethod(value="获取随机颜色值", params={@ApiField("随机对象")}, returns=@ApiField("颜色值"))
	private static int getRandomIntColor(Random random) {
		int[] rgb = getRandomRgb(random);
		int color = 0;
		for (int c : rgb) {
			color = color << 8;
			color = color | c;
		}
		return color;
	}
	
	@ApiMethod(value="获取随机RGB值", params={@ApiField("随机对象")}, returns=@ApiField("RGB值"))
	private static int[] getRandomRgb(Random random) {
		int[] rgb = new int[3];
		for (int i = 0; i < 3; i++) {
			rgb[i] = random.nextInt(255);
		}
		return rgb;
	}

	@ApiMethod(value="使图片扭曲", params={@ApiField("图像对象"), @ApiField(""), @ApiField(""), @ApiField("颜色对象"), @ApiField("随机对象")})
	private static void shear(Graphics g, int w1, int h1, Color color, Random random) {
		shearX(g, w1, h1, color, random);
		shearY(g, w1, h1, color, random);
	}

	@ApiMethod(value="X方向扭曲", params={@ApiField("图像对象"), @ApiField(""), @ApiField(""), @ApiField("颜色对象"), @ApiField("随机对象")})
	private static void shearX(Graphics g, int w1, int h1, Color color, Random random) {
		int period = random.nextInt(2);
		boolean borderGap = true;
		int frames = 1;
		int phase = random.nextInt(2);
		for (int i = 0; i < h1; i++) {
			double d = (double) (period >> 1)
					* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
			g.copyArea(0, i, w1, 1, (int) d, 0);
			if (borderGap) {
				g.setColor(color);
				g.drawLine((int) d, i, 0, i);
				g.drawLine((int) d + w1, i, w1, i);
			}
		}
 
	}

	@ApiMethod(value="Y方向扭曲", params={@ApiField("图像对象"), @ApiField(""), @ApiField(""), @ApiField("颜色对象"), @ApiField("随机对象")})
	private static void shearY(Graphics g, int w1, int h1, Color color, Random random) {
		int period = random.nextInt(40) + 10; // 50;
		boolean borderGap = true;
		int frames = 20;
		int phase = 7;
		for (int i = 0; i < w1; i++) {
			double d = (double) (period >> 1)
					* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
			g.copyArea(i, 0, 1, h1, 0, (int) d);
			if (borderGap) {
				g.setColor(color);
				g.drawLine(i, (int) d, i, 0);
				g.drawLine(i, (int) d + h1, i, h1);
			}
 
		}
	}
	
	@ApiMethod(value="创建java机器人对象", returns = @ApiField("java机器人对象"))
	private static Robot createRobot() {
		try {
			return new Robot();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		}
	}
	
	@ApiMethod(value="全屏截屏", returns = @ApiField("截屏的图片流"))
	public static BufferedImage createFullScreenCapture() {
		Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
		return robot.createScreenCapture(screenRect);
	}
	
	@ApiMethod(value="截屏指定大小", params = {@ApiField("截屏起点x坐标"), @ApiField("截屏起点y坐标"), @ApiField("截屏宽度"), @ApiField("截屏高度")}, returns = @ApiField("截屏的图片流"))
	public static BufferedImage createScreenCapture(int x, int y, int width, int height) {
		Rectangle screenRect = new Rectangle(x, y, width, height);
		return robot.createScreenCapture(screenRect);
	}
}
